package com.ray.business.api;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ray.base.api.CustomerApi;
import com.ray.base.check.CustomerCheck;
import com.ray.base.service.BaseCustomerService;
import com.ray.base.service.BaseMaterialModelService;
import com.ray.base.service.compose.GoodsService;
import com.ray.base.table.dto.MaterialModelQueryDTO;
import com.ray.base.table.entity.BaseCustomer;
import com.ray.base.table.entity.BaseMaterialModel;
import com.ray.base.table.params.customer.CustomerQueryParams;
import com.ray.base.table.vo.customer.CustomerVO;
import com.ray.base.table.vo.material.model.MaterialModelVO;
import com.ray.business.builder.BusinessBuilder;
import com.ray.business.builder.BusinessGoodsVOBuilder;
import com.ray.business.builder.BusinessVOBuilder;
import com.ray.business.check.BusinessCheck;
import com.ray.business.check.OrderCheck;
import com.ray.business.check.OrderStepCheck;
import com.ray.business.enums.BusinessStatusEnum;
import com.ray.business.service.*;
import com.ray.business.table.dto.BusinessQueryDTO;
import com.ray.business.table.entity.*;
import com.ray.business.table.params.business.BusinessCreateParams;
import com.ray.business.table.params.business.BusinessEditParams;
import com.ray.business.table.params.business.BusinessQueryParams;
import com.ray.business.table.vo.BusinessGoodsVO;
import com.ray.business.table.vo.BusinessVO;
import com.ray.magicBlock.BlockDispatch;
import com.ray.system.builder.CommonPageBuilder;
import com.ray.validate.support.utils.ValidateUtil;
import com.ray.wms.service.WmsWarehouseService;
import com.ray.wms.table.entity.WmsWarehouse;
import com.ray.woodencreate.beans.LoginUser;
import com.ray.woodencreate.enums.YesOrNoEnum;
import com.ray.woodencreate.page.CommonPage;
import com.ray.woodencreate.result.MsgCodeConstant;
import com.ray.woodencreate.result.Result;
import com.ray.woodencreate.result.ResultFactory;
import com.ray.woodencreate.util.Assert;
import com.ray.woodencreate.util.LogInUserUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author bo shen
 * @Description: 订单相关服务
 * @Class: BusinessApi
 * @Package com.ray.base.api
 * @date 2020/5/27 11:15
 * @company <p>Ray快速开发平台</p>
 * @updateRecord time(修改时间)  author(修改人)   desc(修改内容)
 */
@Service
@Slf4j
public class BusinessApi {

    @Autowired
    private ProdStepService prodStepService;
    @Autowired
    private BaseCustomerService baseCustomerService;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private ProdOrderStepService prodOrderStepService;
    @Autowired
    private BaseMaterialModelService baseMaterialModelService;
    @Autowired
    private ProdBusinessOutService prodBusinessOutService;
    @Autowired
    private ProdBusinessService prodBusinessService;
    @Autowired
    private ProdOrderService prodOrderService;
    @Autowired
    private WmsWarehouseService wmsWarehouseService;
    @Autowired
    private ProdOrderGoodsService prodOrderGoodsService;
    @Autowired
    private BlockDispatch<BusinessQueryDTO, LoginUser, List<BusinessGoodsVO>> blockDispatch;
    @Autowired
    private BlockDispatch<BusinessCreateParams, LoginUser, String> createDispatch;
    @Autowired
    private BlockDispatch<BusinessEditParams, LoginUser, String> editDispatch;
    @Autowired
    private BlockDispatch<String, LoginUser, String> commonDispatch;
    @Autowired
    private BlockDispatch<ProdBusiness, LoginUser, String> passDispatch;
    @Autowired
    private BlockDispatch<ProdBusiness, LoginUser, BusinessVO> viewDispatch;
    @Autowired
    private CustomerApi customerApi;

    /**
     * 查询订单列表信息 分页  非删除的
     *
     * @param queryParams
     * @return
     */
    public Result<IPage<BusinessVO>> pageBusinesss(CommonPage<BusinessQueryParams, Page<BusinessVO>> queryParams) {
        Assert.notNull(queryParams, "参数[queryParams]不能为空");
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        Map<String, BaseCustomer> baseCustomerMap = new HashMap<>();
        Map<String, WmsWarehouse> wmsWarehouseMap = new HashMap<>();
        Map<String, ProdStep> stepMap = new HashMap<>();
        CommonPageBuilder<BusinessQueryDTO, ProdBusiness> commonPageBuilder = new CommonPageBuilder<>(BusinessQueryDTO.class);
        commonPageBuilder.appendEntity(queryParams.getEntity()).appendQuery(queryParams.getQuery()).appendPage(queryParams.getPage());
        IPage<ProdBusiness> page = prodBusinessService.page(commonPageBuilder.bulid(), loginUser);
        List<ProdBusiness> orders = page.getRecords();
        //结果对象
        IPage<BusinessVO> pageList = new Page<>();
        pageList.setTotal(page.getTotal());
        pageList.setCurrent(page.getCurrent());
        pageList.setSize(page.getSize());
        //查询到结果 数据转换
        if (ObjectUtil.isNotNull(orders)) {
            pageList.setRecords(orders.stream().map(sysBusiness -> {
                //查询客信息
                BaseCustomer baseCustomer = baseCustomerMap.get(sysBusiness.getCustomerCode());
                if (ObjectUtil.isEmpty(baseCustomer)) {
                    baseCustomer = baseCustomerService.queryCustomerByCustomerCode(sysBusiness.getCustomerCode(), loginUser);
                    baseCustomerMap.put(sysBusiness.getCustomerCode(), baseCustomer);
                }
                //查询仓库信息
                WmsWarehouse wmsWarehouse = wmsWarehouseMap.get(sysBusiness.getWarehouseCode());
                if (ObjectUtil.isEmpty(wmsWarehouse)) {
                    wmsWarehouse = wmsWarehouseService.queryWarehouseByWarehouseCode(sysBusiness.getWarehouseCode(), loginUser);
                    wmsWarehouseMap.put(wmsWarehouse.getWarehouseCode(), wmsWarehouse);
                }
                //工序信息
                ProdStep prodStep = stepMap.get(sysBusiness.getStepCode());
                if (ObjectUtil.isEmpty(prodStep)) {
                    prodStep = prodStepService.queryStepByStepCode(sysBusiness.getStepCode(), loginUser);
                    stepMap.put(sysBusiness.getStepCode(), prodStep);
                }
                return new BusinessVOBuilder().append(sysBusiness).append(baseCustomer).append(wmsWarehouse).append(prodStep).bulid();
            }).collect(Collectors.toList()));
        } else {
            pageList.setRecords(new ArrayList<>());
        }
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, pageList);
    }


    /**
     * 查询订单可以出库的列表
     *
     * @param businessQueryParams
     * @return
     */
    public Result<List<BusinessGoodsVO>> listOutGoods(BusinessQueryParams businessQueryParams) {
        Assert.notNull(businessQueryParams, "参数[businessQueryParams]不能为空");
        ValidateUtil.validate(businessQueryParams);
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        //步骤第一个订单的出库物料获取
        String strategy = "order";
        //查询步骤顺序
        ProdOrderStep prodOrderStep = prodOrderStepService.queryOrderStepByStepCode(businessQueryParams.getOrderNo(), businessQueryParams.getStepCode(), loginUser);
        new OrderStepCheck(prodOrderStep).checkNull("订单配置步骤数据不存在");
        if (prodOrderStep.getIndexSort() != 1) {
            strategy = "step";
        }
        BusinessQueryDTO businessQueryDTO = new BusinessQueryDTO();
        BeanUtil.copyProperties(businessQueryParams, businessQueryDTO);
        businessQueryDTO.setOrderStep(prodOrderStep);
        List<BusinessGoodsVO> goodsVOS = blockDispatch.dispatch("outGoods", strategy, businessQueryDTO, loginUser);
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, goodsVOS);
    }

    /**
     * 查询订单可以出库的列表
     *
     * @param businessQueryParams
     * @return
     */
    public Result<List<BusinessGoodsVO>> listBackOutGoods(BusinessQueryParams businessQueryParams) {
        Assert.notNull(businessQueryParams, "参数[businessQueryParams]不能为空");
        ValidateUtil.validate(businessQueryParams);
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        String strategy = "stepBack";
        //查询步骤顺序
        ProdOrderStep thisStep = prodOrderStepService.queryOrderStepByStepCode(businessQueryParams.getOrderNo(), businessQueryParams.getStepCode(), loginUser);
        new OrderStepCheck(thisStep).checkNull("订单配置步骤数据不存在");
        BusinessQueryDTO businessQueryDTO = new BusinessQueryDTO();
        BeanUtil.copyProperties(businessQueryParams, businessQueryDTO);
        businessQueryDTO.setOrderStep(thisStep);
        List<BusinessGoodsVO> goodsVOS = blockDispatch.dispatch("outGoods", strategy, businessQueryDTO, loginUser);
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, goodsVOS);
    }


    /**
     * 查询订单可以入库的列表
     *
     * @param businessQueryParams
     * @return
     */
    public Result<List<BusinessGoodsVO>> listInGoods(BusinessQueryParams businessQueryParams) {
        Assert.notNull(businessQueryParams, "参数[businessQueryParams]不能为空");
        Assert.hasLength(businessQueryParams.getCustomerCode(), "请选择客户");
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        //查询步骤顺序
        ProdOrderStep prodOrderStep = prodOrderStepService.queryOrderStepByStepCode(businessQueryParams.getOrderNo(), businessQueryParams.getStepCode(), loginUser);
        new OrderStepCheck(prodOrderStep).checkNull("订单配置步骤数据不存在");
        //查询订单对应的采购订单
        List<ProdBusiness> prodBusinesses = prodBusinessService.listByOrderNo(businessQueryParams.getOrderNo(), businessQueryParams.getStepCode(),
                businessQueryParams.getCustomerCode(), loginUser);
        if (ObjectUtil.isNotEmpty(prodBusinesses)) {
            //查询
            List<String> businessCodes = prodBusinesses.stream().map(ProdBusiness::getBusinessCode).collect(Collectors.toList());
            //查询出库单信息
            List<BusinessGoodsVO> prodPurchaseRecords = prodBusinessOutService.list(businessCodes, loginUser)
                    .stream().map(prodBusinessOut -> {
                        //查询商品详情
                        MaterialModelVO modelVO = goodsService.queryGoodsByCode(prodBusinessOut.getGoodsCode(), loginUser);
                        //商品构建
                        BusinessGoodsVO businessGoodsVO = new BusinessGoodsVOBuilder()
                                .append(modelVO).append(prodBusinessOut).bulid();
                        return businessGoodsVO;
                    }).collect(Collectors.toList());
            return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, prodPurchaseRecords);
        }
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, new ArrayList<>());
    }

    /**
     * 创建加工业务入库单
     *
     * @return
     */
    @Transactional
    public Result<String> createBusinessIn(BusinessCreateParams createParams) {
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        //判断订单是否存在
        ProdOrder prodOrder = prodOrderService.queryOrderByOrderCode(createParams.getOrderNo(), loginUser);
        new OrderCheck(prodOrder).checkNull("订单数据不存在").checkProd("订单状态未审批通过");
        //判断客户是否存在
        BaseCustomer baseCustomer = baseCustomerService.queryCustomerByCustomerCode(createParams.getCustomerCode(), loginUser);
        new CustomerCheck(baseCustomer).checkNull(String.format("%s未查询到客户", createParams.getCustomerCode()));
        String businessCode = createDispatch.dispatch("createBusiness", "in", createParams, loginUser);
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, businessCode);

    }


    /**
     * 创建加工业务出库单
     *
     * @return
     */
    @Transactional
    public Result<String> createBusinessOut(BusinessCreateParams createParams) {
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        //判断订单是否存在
        ProdOrder prodOrder = prodOrderService.queryOrderByOrderCode(createParams.getOrderNo(), loginUser);
        new OrderCheck(prodOrder).checkNull("订单数据不存在").checkProd("订单状态未审批通过");
        //判断客户是否存在
        BaseCustomer baseCustomer = baseCustomerService.queryCustomerByCustomerCode(createParams.getCustomerCode(), loginUser);
        new CustomerCheck(baseCustomer).checkNull(String.format("%s未查询到客户", createParams.getCustomerCode()));
        String businessCode = createDispatch.dispatch("createBusiness", "out", createParams, loginUser);
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, businessCode);
    }

    /**
     * 编辑加工业务出库单
     *
     * @return
     */
    @Transactional
    public Result<String> editBusiness(BusinessEditParams editParams) {
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        ProdBusiness business = prodBusinessService.queryBusinessByBusinessCode(editParams.getBusinessCode(), loginUser);
        new BusinessCheck(business).checkNull("业务加工单不存在").checkCanEdit("订单不能编辑");
        //判断订单是否存在
        ProdOrder prodOrder = prodOrderService.queryOrderByOrderCode(editParams.getOrderNo(), loginUser);
        new OrderCheck(prodOrder).checkNull("订单数据不存在").checkProd("订单状态未审批通过");
        //判断客户是否存在
        BaseCustomer baseCustomer = baseCustomerService.queryCustomerByCustomerCode(editParams.getCustomerCode(), loginUser);
        new CustomerCheck(baseCustomer).checkNull(String.format("%s未查询到客户", editParams.getCustomerCode()));
        String businessCode = editDispatch.dispatch("editBusiness", business.getBusinessType().toLowerCase(), editParams, loginUser);
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, businessCode);
    }


    /**
     * 删除
     *
     * @return
     */
    @Transactional
    public Result<String> deleteBusiness(String businessCode) {
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        ProdBusiness business = prodBusinessService.queryBusinessByBusinessCode(businessCode, loginUser);
        new BusinessCheck(business).checkNull("业务加工单不存在").checkCanDelete("订单不能删除");
        //删除业务单
        commonDispatch.dispatch("deleteBusiness", business.getBusinessType().toLowerCase(), businessCode, loginUser);
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, businessCode);
    }


    /**
     * 审核
     *
     * @return
     */
    @Transactional
    public Result<String> passBusiness(String businessCode) {
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        ProdBusiness business = prodBusinessService.queryBusinessByBusinessCode(businessCode, loginUser);
        new BusinessCheck(business).checkNull("业务加工单不存在").checkCanCheck("订单已审核");
        //审核业务单
        passDispatch.dispatch("passBusiness", business.getBusinessType().toLowerCase(), business, loginUser);
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, businessCode);
    }

    /**
     * 审核
     *
     * @return
     */
    @Transactional
    public Result<String> finishBusiness(String businessCode) {
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        ProdBusiness business = prodBusinessService.queryBusinessByBusinessCode(businessCode, loginUser);
        new BusinessCheck(business).checkNull("业务加工单不存在").checkNotFinish("订单还未完成").checkOutType("只有出库加工单才能操作");
        BusinessBuilder businessBuilder = new BusinessBuilder();
        businessBuilder.appendCode(businessCode).appendEdit(loginUser).appendStatus(YesOrNoEnum.YES.getValue());
        //更新
        prodBusinessService.edit(businessBuilder.bulid(), loginUser);
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, businessCode);
    }

    /**
     * 审核
     *
     * @return
     */
    @Transactional
    public Result<String> openBusiness(String businessCode) {
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        ProdBusiness business = prodBusinessService.queryBusinessByBusinessCode(businessCode, loginUser);
        new BusinessCheck(business).checkNull("业务加工单不存在").checkNotFinish("订单还未完成").checkOutType("只有出库加工单才能操作");
        BusinessBuilder businessBuilder = new BusinessBuilder();
        businessBuilder.appendCode(businessCode).appendEdit(loginUser).appendStatus(YesOrNoEnum.NO.getValue());
        //更新
        prodBusinessService.edit(businessBuilder.bulid(), loginUser);
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, businessCode);
    }

    /**
     * 取消
     *
     * @return
     */
    @Transactional
    public Result<String> cancelBusiness(String businessCode) {
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        ProdBusiness business = prodBusinessService.queryBusinessByBusinessCode(businessCode, loginUser);
        new BusinessCheck(business).checkNull("业务加工单不存在").checkCanCancel("订单不能取消");
        //取消业务单
        commonDispatch.dispatch("cancelBusiness", business.getBusinessType().toLowerCase(), businessCode, loginUser);
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, businessCode);
    }


    /**
     * 取消
     *
     * @return
     */
    public Result<BusinessVO> viewBusiness(String businessCode) {
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        ProdBusiness business = prodBusinessService.queryBusinessByBusinessCode(businessCode, loginUser);
        new BusinessCheck(business).checkNull("业务加工单不存在");
        //业务单详情
        BusinessVO businessVO = viewDispatch.dispatch("viewBusiness", business.getBusinessType().toLowerCase(), business, loginUser);
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, businessVO);
    }

    /**
     * 查询订单对应的商品
     *
     * @param queryParams
     * @return
     */
    public Result<IPage<MaterialModelVO>> pageMaterialModels(CommonPage<BusinessQueryParams, Page<MaterialModelVO>> queryParams) {
        Assert.notNull(queryParams, "参数[queryParams]不存在");
        Assert.notNull(queryParams.getEntity(), "参数[entity]不存在");
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        BusinessQueryParams businessQueryParams = queryParams.getEntity();
        //判断工序是否最后一步
        ProdOrderStep prodOrderStep = prodOrderStepService.queryOrderStepByStepCode(businessQueryParams.getOrderNo(), businessQueryParams.getStepCode(), loginUser);
        if (ObjectUtil.isNotNull(prodOrderStep)) {
            //查询工序的下一步
            ProdOrderStep last = prodOrderStepService.queryOrderStepByIndexSort(businessQueryParams.getOrderNo(), prodOrderStep.getIndexSort() + 1, loginUser);
            if (ObjectUtil.isNull(last)) {
                //查询订单商品
                List<String> goodsCodes = prodOrderGoodsService.list(businessQueryParams.getOrderNo(), loginUser).stream()
                        .map(ProdOrderGoods::getGoodsCode).collect(Collectors.toList());
                businessQueryParams.setModelCodes(goodsCodes);
            }
        }
        CommonPageBuilder<MaterialModelQueryDTO, BaseMaterialModel> commonPageBuilder = new CommonPageBuilder<>(MaterialModelQueryDTO.class);
        commonPageBuilder.appendEntity(queryParams.getEntity()).appendQuery(queryParams.getQuery()).appendPage(queryParams.getPage());
        IPage<BaseMaterialModel> page = baseMaterialModelService.page(commonPageBuilder.bulid(), loginUser);
        List<BaseMaterialModel> materials = page.getRecords();
        //结果对象
        IPage<MaterialModelVO> pageList = new Page<>();
        pageList.setTotal(page.getTotal());
        pageList.setCurrent(page.getCurrent());
        pageList.setSize(page.getSize());
        //查询到结果 数据转换
        if (ObjectUtil.isNotNull(materials)) {
            pageList.setRecords(materials.stream().map(sysMaterialModel -> {
                MaterialModelVO materialModelVO = goodsService.queryGoodsByCode(sysMaterialModel.getModelCode(), loginUser);
                return materialModelVO;
            }).collect(Collectors.toList()));
        } else {
            pageList.setRecords(new ArrayList<>());
        }
        return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, pageList);
    }

    /**
     * 入库客户列表
     * @param queryParams
     * @return
     */
    public Result<List<CustomerVO>> listCustomer(BusinessQueryParams queryParams) {
        LoginUser loginUser = LogInUserUtil.get();
        //查询当前出库单
        List<ProdBusiness> prodBusinesses = prodBusinessService.listOutByOrderNoAndSetpCode(queryParams.getOrderNo(),queryParams.getStepCode(),loginUser);
        if(ObjectUtil.isEmpty(prodBusinesses)){
            return ResultFactory.createSuccessResult(MsgCodeConstant.Success.SUC00000002, new ArrayList<>());
        }
        List<String> customerCodes = prodBusinesses.stream().map(ProdBusiness::getCustomerCode).collect(Collectors.toList());
        CustomerQueryParams customerQueryParams = new CustomerQueryParams();
        customerQueryParams.setCustomerCodes(customerCodes);
        return customerApi.queryCustomers(customerQueryParams);
    }
}
